Loading Libraries

# load libraries

library(quanteda)
library(readtext)
library(wordcloud)
library(RColorBrewer)
library(wordcloud2)
library(tidyverse)
library(tm)
library("textcat")
library("quanteda.textplots")
library("quanteda.textstats")
library("gsubfn")
library("spacyr")

spacy_initialize(model = "de_core_news_sm")

Start here to load existing corpora:

# load corpus files 
full_corpus = readRDS("corpora/full_corpus.rds")
full_corpus_sents = readRDS("corpora/full_corpus_sents.rds")

pro_corpus = readRDS("corpora/pro_corpus.rds")
contra_corpus = readRDS("corpora/contra_corpus.rds")

pro2000 = readRDS("corpora/pro2000.rds")
pro900 = readRDS("corpora/pro900.rds")
contra2000 = readRDS("corpora/contra2000.rds")
contra900 = readRDS("corpora/contra900.rds")

fff_de_corpus = readRDS("corpora/fff_de_corpus.rds")
ikem_corpus = readRDS("corpora/ikem_corpus.rds")
klimarep_corpus = readRDS("corpora/klimarep_corpus.rds")
klimafakten_corpus = readRDS("corpora/klimafakten_corpus.rds")
zero_corpus = readRDS("corpora/zero_corpus.rds")
komma_corpus = readRDS("corpora/komma_corpus.rds")
eike_corpus = readRDS("corpora/eike_corpus.rds")
ffh_corpus = readRDS("corpora/ffh_corpus.rds")

Exploring the corpus

Corpus statistics

```r
# to get index number 
#id_pro = 1:ndoc(pro900)

<!-- rnb-source-end -->

<!-- rnb-chunk-end -->


<!-- rnb-text-begin -->


# Plotting Number of Sentences


<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxucHJvMjAwMF9zdW0gPC0gc3VtbWFyeShwcm8yMDAwLCBuZG9jKHBybzIwMDApKVxuY29udHJhMjAwMF9zdW0gPC0gc3VtbWFyeShjb250cmEyMDAwKVxucHJvOTAwX3N1bSA8LSBzdW1tYXJ5KHBybzkwMCwgbmRvYyhwcm85MDApKVxuY29udHJhOTAwX3N1bSA8LSBzdW1tYXJ5KGNvbnRyYTkwMCwgbmRvYyhjb250cmE5MDApKVxuXG4jdG8gZ2V0IGlkIGFzIHggYXhpc1xuI2lkX3Byb1sxOjEwMF1cbiNjb250cmE5MDBfc3VtJGlkXG5cbmdncGxvdChwcm8yMDAwX3N1bSwgYWVzKGlkLCBTZW50ZW5jZXMsIGdyb3VwPTEpKSArXG4gIGdlb21fbGluZSgpICsgXG4gIGdlb21fcG9pbnQoKSArXG4gIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTAsIHZqdXN0PTEsIGhqdXN0PTEpKSArIFxuICBnZ3RpdGxlKFwiU2VudGVuY2VzIFBybzIwMDBcIilcbmBgYCJ9 -->

```r
pro2000_sum <- summary(pro2000, ndoc(pro2000))
contra2000_sum <- summary(contra2000)
pro900_sum <- summary(pro900, ndoc(pro900))
contra900_sum <- summary(contra900, ndoc(contra900))

#to get id as x axis
#id_pro[1:100]
#contra900_sum$id

ggplot(pro2000_sum, aes(id, Sentences, group=1)) +
  geom_line() + 
  geom_point() +
  theme(axis.text.x = element_text(angle=0, vjust=1, hjust=1)) + 
  ggtitle("Sentences Pro2000")


ggplot(contra2000_sum, aes(id, Sentences, group=1)) +
  geom_line() + 
  geom_point() +
  theme(axis.text.x = element_text(angle=0, vjust=1, hjust=1)) + 
  ggtitle("Sentences Contra2000")

pro900_sum <- summary(pro900, n=100)
contra900_sum <- summary(contra900, n=100)


ggplot(pro900_sum, aes(pro900_sum$id, Tokens, group=1)) +
  geom_line() + 
  geom_point() +
  theme(axis.text.x = element_text(angle=0, vjust=1, hjust=1)) + 
  ggtitle("Tokens Pro900")


ggplot(contra900_sum, aes(contra900_sum$id, Tokens, group=1)) +
  geom_line() + 
  geom_point() +
  theme(axis.text.x = element_text(angle=0, vjust=1, hjust=1)) + 
  ggtitle("Tokens Contra900")

ggplot(pro900_sum, aes(pro900_sum$id, Types, group=1)) + 
  geom_line() + 
  geom_point() +
  theme(axis.text.x = element_text(angle=0, vjust=1, hjust=1)) + 
  ggtitle("Types Pro900")


ggplot(contra900_sum, aes(contra900_sum$id, Types, group=1)) +
  geom_line() + 
  geom_point() +
  theme(axis.text.x = element_text(angle=0, vjust=1, hjust=1)) + 
  ggtitle("Types Contra900")

NA
NA
ggplot(pro900_sum, aes(Tokens, Types, group=1, label= id)) +
  geom_smooth(method = "lm", formula ="y ~ x", se = FALSE) +
  geom_text(check_overlap = T) +
  ggtitle("Type-Token-Relation Pro900")


ggplot(contra900_sum, aes(Tokens, Types, group=1, label= id)) +
  geom_smooth(method = "lm", formula ="y ~ x", se = FALSE) +
  geom_text(check_overlap = T) +
  ggtitle("Type-Token-Relation Contra900")

<<<<<<< Updated upstream # Word Frequencies

1. Step: Create DFM, Load Stoplists

# stoplists
de_stopwords <- stopwords::stopwords("de", source="snowball")
en_stopwords <- stopwords::stopwords("en", source="snowball" )
custom_stopwords <- read.table("de_complete.txt", header=F, sep="\n")



# add own stopwords 
full_stopwords <- c(de_stopwords, "dass", "=", "the", "seit", "ab", "beim", "\n", "mal", "c", "|", "m", "kommentare", "neueste", "gepostet", custom_stopwords, en_stopwords)
de_stopwords1 <- c(de_stopwords, "dass", "=", "the", "seit", "ab", "beim", "\n", "mal", "c", "|", "m", "kommentare", "neueste", "gepostet")

# create dfm
dfm_p2000 <- dfm(pro2000, remove=full_stopwords, remove_punct=TRUE, remove_numbers=TRUE)
Warnung: 'dfm.corpus()' is deprecated. Use 'tokens()' first.
Warnung: '...' should not be used for tokens() arguments; use 'tokens()' first.
Warnung: 'remove' is deprecated; use dfm_remove() instead
dfm_c2000 <- dfm(contra2000, remove=full_stopwords, remove_punct=TRUE, remove_numbers=TRUE)
Warnung: 'dfm.corpus()' is deprecated. Use 'tokens()' first.
Warnung: '...' should not be used for tokens() arguments; use 'tokens()' first.
Warnung: 'remove' is deprecated; use dfm_remove() instead

Corpus Cleaning: Lemmatization -> new lemmatized dfm

# pro 
sp_pro2000 <- spacy_parse(pro2000, pos=FALSE, entity=FALSE, dependency=FALSE)
Warnung in spacy_parse.character(pro2000, pos = FALSE, entity = FALSE, dependency = FALSE)
  lemmatization may not work properly in model 'de_core_news_sm'
sp_pro2000$token <- sp_pro2000$lemma

sp_dfm_p2000 <- as.tokens(sp_pro2000)%>%
  dfm(remove=full_stopwords, remove_punct=TRUE, remove_numbers=TRUE, tolower=TRUE)
Warnung: '...' should not be used for tokens() arguments; use 'tokens()' first.
Warnung: 'remove' is deprecated; use dfm_remove() instead
# contra
sp_contra2000 <- spacy_parse(contra2000, pos=FALSE, entity=FALSE, dependency=FALSE)
Warnung in spacy_parse.character(contra2000, pos = FALSE, entity = FALSE, 
  lemmatization may not work properly in model 'de_core_news_sm'
sp_contra2000$token <- sp_contra2000$lemma

sp_dfm_c2000 <- as.tokens(sp_contra2000)%>%
  dfm(remove=full_stopwords, remove_punct=TRUE, remove_numbers=TRUE, tolower=TRUE)
Warnung: '...' should not be used for tokens() arguments; use 'tokens()' first.
Warnung: 'remove' is deprecated; use dfm_remove() instead
dfm_p2000
Document-feature matrix of: 2,000 documents, 60,243 features (99.72% sparse) and 4 docvars.
                  features
docs               klima update ° folge extremwetter eu-klimaplan versicherungswende wütet weltweit eu-kommission
  kr_00007.txt         3      3 3     1            3            1                  1     2        2             1
  ikem_01141.txt       0      0 0     0            0            0                  0     0        0             0
  fff_de_00121.txt     0      0 0     0            0            0                  0     0        0             0
  ikem_00898.txt       0      0 0     0            0            0                  0     0        0             0
  ikem_00709.txt       0      0 0     0            0            0                  0     0        0             0
  ikem_00588.txt       0      0 0     0            0            0                  0     0        0             0
[ reached max_ndoc ... 1,994 more documents, reached max_nfeat ... 60,233 more features ]
dfm_c2000
Document-feature matrix of: 2,000 documents, 150,974 features (99.71% sparse) and 4 docvars.
                features
docs             interne ermittler schule glauben ehemalige labortechnikerin erin potts-kant daten medizinische
  eike_05241.txt       1         1      2       1         2                1    1          6     7            1
  eike_07670.txt       0         0      0       0         0                0    0          0     0            0
  eike_12660.txt       0         0      0       0         0                0    0          0     0            0
  eike_13073.txt       0         0      0       0         0                0    0          0     0            0
  eike_09381.txt       0         0      0       0         0                0    0          0     0            0
  eike_05930.txt       0         0      0       0         0                0    0          0     0            0
[ reached max_ndoc ... 1,994 more documents, reached max_nfeat ... 150,964 more features ]

2. Step: Check Topfeatures of DFM -> most frequently occuring terms

topfeatures(sp_dfm_p2000, n=50)
        mehr          uhr         ikem       mensch         jahr         weit  deutschland        geben      energie        thema      aktuell 
        4283         3497         2657         2464         2062         1698         1645         1602         1592         1402         1362 
      sollen         groß        gehen  klimaschutz          gut        sowie        immer      bleiben  information       müssen        schon 
        1323         1319         1301         1289         1276         1207         1156         1152         1151         1144         1084 
       dabei       future       arbeit       stehen energiewende      politik       finden        welch         land      projekt         ziel 
        1020          992          977          926          901          895          891          886          876          869          863 
     wichtig       berlin       kommen      fridays     erfahren          jed      zukunft   klimakrise   newsletter         ganz          neu 
         851          846          838          831          825          816          813          796          780          769          750 
      rahmen     laufende      möglich         erst     anmelden        frage 
         748          741          735          721          720          717 
topfeatures(sp_dfm_c2000, n=50)
       jahr       geben        mehr       schon       immer         co2         gut      kommen          ja       gehen        weit deutschland 
       9197        6646        6328        4722        4289        4114        4067        4056        3951        3821        3786        3643 
     sollen      mensch       sagen        groß       welch         jed      zeigen     energie        hoch       wenig        ganz      global 
       3640        3559        3448        3378        3332        3286        3102        2921        2883        2869        2834        2523 
      sehen      müssen  temperatur       strom        herr   natürlich      stehen     einfach           °        zeit       klima        erst 
       2503        2480        2423        2399        2381        2236        2234        2226        2221        2215        2196        2154 
     finden       heute       frage        land klimawandel      liegen        etwa   erwärmung       genau      wissen        erde        welt 
       2121        2064        2048        2001        1944        1912        1901        1856        1852        1852        1824        1822 
 atmosphäre         tun 
       1808        1804 
tf_p2000 <- topfeatures(sp_dfm_p2000, n=50)
tf_c2000 <- topfeatures(sp_dfm_c2000, n=50)
textstat_frequency(sp_dfm_p2000, n=50)

Plotting word frequencies

klima_p2000 <- dfm_select(sp_dfm_p2000, pattern="klima*")
klima_c2000 <- dfm_select(sp_dfm_c2000, pattern="klima*")
freq_p2000 <- textstat_frequency(sp_dfm_p2000, n=50)
freq_c2000 <- textstat_frequency(sp_dfm_c2000, n=50)

plot_p2000 <- with(freq_p2000, reorder(feature, -frequency))
plot_c2000 <- with(freq_c2000, reorder(feature, -frequency))

#create plot for eike klima words frequencies
plot1 <- ggplot(freq_p2000, aes(x=feature, y=frequency)) + 
  geom_point()+ggtitle("P2000 Frequencies")+
  theme(axis.text.x = element_text(angle=90,hjust=1))
#ggsave(plot=plot1, width = 10, height = 5, dpi=300, filename="klima_eike_plot.jpeg" )
plot1


#create plot for klimareporter klima words frequencies
plot2 <- ggplot(freq_c2000, aes(x=feature, y=frequency)) + 
  geom_point()+ ggtitle("C2000 Frequencies")+
  theme(axis.text.x = element_text(angle=90,hjust=1)) 
  
#ggsave(plot=plot2, width = 10, height = 5, dpi=300, filename="klima_klimarep_plot.jpeg" )
plot2

Same Plot for “Klima” Words

freq_klima_p2000 <- textstat_frequency(klima_p2000, n=50)
freq_klima_c2000 <- textstat_frequency(klima_c2000, n=50)

freq_klima_p2000$feature <- with(freq_klima_p2000, reorder(feature, -frequency))
freq_klima_c2000$feature <- with(freq_klima_c2000, reorder(feature, -frequency))

#create plot for eike klima words frequencies
plot1 <- ggplot(freq_klima_p2000, aes(x=feature, y=frequency)) + 
  geom_point()+ggtitle("P2000 Klima Frequencies")+
  theme(axis.text.x = element_text(angle=90,hjust=1))
#ggsave(plot=plot1, width = 10, height = 5, dpi=300, filename="klima_eike_plot.jpeg" )
plot1


#create plot for klimareporter klima words frequencies
plot2 <- ggplot(freq_klima_c2000, aes(x=feature, y=frequency)) + 
  geom_point()+ ggtitle("C2000 Klima Frequencies")+
  theme(axis.text.x = element_text(angle=90,hjust=1)) 
  
#ggsave(plot=plot2, width = 10, height = 5, dpi=300, filename="klima_klimarep_plot.jpeg" )
plot2

Plot TF-IDF (not working yet!!!)

# weighted words
p2000_weight <- dfm_weight(sp_dfm_p2000, scheme="prop")
c2000_weight <- dfm_weight(sp_dfm_c2000, scheme="prop")

relfreq_p2000 <- textstat_frequency(p2000_weight, n=50)
relfreq_c2000 <- textstat_frequency(c2000_weight, n=50)

#tfidf
p2000_tfidf <- dfm_tfidf(sp_dfm_p2000)
c2000_tfidf <- dfm_tfidf(sp_dfm_c2000)

#plot3 <- with(relfreq_p2000, reorder(feature, -freqency))
relfreq_p2000$feature <- with(relfreq_p2000, reorder(feature, -frequency))
plot3 <- ggplot(relfreq_p2000, aes(x=feature, y=frequency)) + 
  geom_point()+ggtitle("P2000 Frequencies")+
  theme(axis.text.x = element_text(angle=90,hjust=1))
#ggsave(plot=plot1, width = 10, height = 5, dpi=300, filename="klima_eike_plot.jpeg" )
plot3

pro_freq_tfidf <- p2000_tfidf %>%
  textstat_frequency(n=10, force=TRUE)

con_freq_tfidf <- c2000_tfidf %>%
  textstat_frequency(n=10, force=TRUE)

tplot_tfidf_p2000 <- ggplot(data=pro_freq_tfidf,
                      aes(x=factor(nrow(pro_freq_tfidf):1),
                          y=frequency)) +
  geom_point() +
  coord_flip() +
  scale_x_discrete(breaks=factor(nrow(pro_freq_tfidf):1),
                   labels=pro_freq_tfidf$feature) +
  labs(x=NULL, y="tf-idf")

tplot_tfidf_p2000


tplot_tfidf_c2000 <- ggplot(data=con_freq_tfidf,
                      aes(x=factor(nrow(con_freq_tfidf):1),
                          y=frequency)) +
  geom_point() +
  coord_flip() +
  scale_x_discrete(breaks=factor(nrow(con_freq_tfidf):1),
                   labels=con_freq_tfidf$feature) +
  labs(x=NULL, y="tf-idf")

tplot_tfidf_c2000

topfeatures(p2000_tfidf, n=20)
        uhr      infos|        jahr     cookies     energie       geben        mehr        weit         gut      sollen 
  3974.9600   1661.5255   1179.1861   1053.8321   1004.2084    964.5001    930.1357    920.5165    904.4967    869.9748 
      gehen deutschland       schon       immer        groß       12:00      müssen       sowie      future klimaschutz 
   867.1851    864.9142    852.5468    824.5968    823.4997    818.0000    786.1433    774.9726    764.6637    759.5081 
topfeatures(c2000_tfidf, n=20)
       jahr         co2       geben        mehr          ja           °       strom       schon  temperatur deutschland 
   2420.699    2202.477    1859.821    1802.421    1683.002    1667.530    1630.969    1585.781    1569.662    1547.591 
       herr  atmosphäre       immer      mensch         gut           w       gehen      zeigen      kommen      global 
   1458.625    1402.981    1394.521    1381.877    1361.991    1328.953    1312.218    1296.439    1287.389    1285.063 
#p2000_weight

#textstat_frequency(p2000_tfidf, n=10)

Comparison of Groups/Origin

Collocations

# to remove special chars from corpus
pro2000 <- gsub("\\|", "", pro2000)
pro2000 <- gsub("=", "", pro2000)

# convert into collocation dataframe
p_coll <- textstat_collocations(pro2000, min_count=50)
arrange(p_coll, desc(count))
# transform stoplists for dplyr::filter function (why?)
de_stps <- paste0(de_stopwords, collapse = "\\b|\\b")
en_stps <- paste0(en_stopwords, collapse = "\\b|\\b")

# remove entries involving stopwords: NOT WORKING YET!
p2000_coll_clean <- p_coll %>%
  dplyr::filter(!str_detect(collocation, de_stps),
                !str_detect(collocation, en_stps),
                !str_detect(collocation, "="))

#p2000_coll_clean
arrange(p2000_coll_clean, desc(count))
# collocations mit vorherigem stopwords removal
p2000_toks <- tokens(pro2000)
p2000_toks_sw <- tokens_select(p2000_toks, pattern=full_stopwords, selection="remove")

p2000_coll <- textstat_collocations(p2000_toks_sw, min_count=3)
arrange(p2000_coll, desc(count))
summary(full_corpus, n=5)
Corpus consisting of 4000 documents, showing 5 documents:

             Text Types Tokens Sentences origin language     group
     kr_00007.txt   196    284        19     kr   german activists
   ikem_01141.txt    27     30         2   ikem   german activists
 fff_de_00121.txt   105    178        11 fff_de   german activists
   ikem_00898.txt   211    880        32   ikem   german activists
   ikem_00709.txt    20     43         3   ikem   german activists

Comparison Plots

ggplot(freqs) +
  geom_segment(aes(x=feature, xend=feature, y=frequency.x, yend=frequency.y), color="grey") +
  geom_point(aes(x=feature, y=frequency.x), color = "red", size = 3 ) +
  geom_point(aes(x=feature, y=frequency.y), color = "lightblue", size = 3 ) +
  ggtitle("Word Frequencies") + 
  xlab("") + ylab("Wortfrequenz") + 
  coord_flip()
Warnung: Removed 1 rows containing missing values (geom_segment).
Warnung: Removed 1 rows containing missing values (geom_point).

p+labs(colour="Group")
Warnung: Removed 1 rows containing missing values (geom_segment).
Warnung: Removed 1 rows containing missing values (geom_point).

as.tokens(sp_pro2000) %>%
  dfm()
Document-feature matrix of: 2,000 documents, 54,656 features (99.63% sparse) and 0 docvars.
                  features
docs               klima update ° – folge 35 \n extremwetter  , eu-klimaplan
  kr_00007.txt         3      3 3 3     1  1  8            3  8            1
  ikem_01141.txt       0      0 0 0     0  0  2            0  1            0
  fff_de_00121.txt     0      0 0 0     0  0  6            0  9            0
  ikem_00898.txt       0      0 0 0     0  0 24            0 28            0
  ikem_00709.txt       0      0 0 0     0  0 12            0  0            0
  ikem_00588.txt       0      0 0 3     0  0 45            0 42            0
[ reached max_ndoc ... 1,994 more documents, reached max_nfeat ... 54,646 more features ]
dfm_weight_corp <- full_corpus %>%
  tokens(remove_punct = TRUE) %>%
  tokens_remove(de_stopwords1) %>%
  dfm() %>%
  dfm_weight(scheme = "prop")

# Calculate relative frequency by president
freq_weight <- textstat_frequency(dfm_weight_corp, n = 10, 
                                  groups = dfm_weight_corp$origin)

ggplot(data = freq_weight, aes(x = nrow(freq_weight):1, y = frequency)) +
     geom_point() +
     facet_wrap(~ group, scales = "free") +
     coord_flip() +
     scale_x_continuous(breaks = nrow(freq_weight):1,
                        labels = freq_weight$feature) +
     labs(x = NULL, y = "Relative frequency")

summary(full_corpus, n=10)

Keyness

Comparison Cloud

full_corpus %>%
    tokens(remove_punct = TRUE, remove_numbers=TRUE) %>%
    tokens_remove(de_stopwords1) %>%
    dfm() %>%
    dfm_group(groups = group) %>%
    dfm_trim(min_termfreq = 5, verbose = FALSE) %>%
    textplot_wordcloud(comparison = TRUE, max_words=100)

                       #,color=c("lightblue","blue"))
textplot_xray(
    kwic(tokens(pro2000), pattern = "klima*"),
    kwic(tokens(contra2000), pattern = "klima*"))

Topic Modeling

library(tidytext)
Fehler in library(tidytext) : es gibt kein Paket namens ‘tidytext’
dfm_full <- dfm(full_corpus, remove=de_stopwords1, remove_punct=TRUE, remove_numbers=TRUE)
dfm_full

tm_full<-convert(dfm_full, to="topicmodels")

topicModel <- LDA(tm_full, k=5, method="Gibbs", control=list(iter = 500, verbose = 25))
terms(topicModel, 10)

Ideas: DONE: Wordcloud Plot of Comparison Group: https://quanteda.io/articles/pkgdown/examples/plotting.html

Lexical Dispersion Plot (X-Ray) -> could be done for keywords "klima*"

Next: - Calculate “Corpus Similarity” - Klimawörter Liste mit Group und Counts abspeichern -> welche Klimawörter gibt es wo und wie oft - alles mit der “Sents” Version testen - Analyse der Ergebnisse - Literatur-Recherche zu den Textmining Themen

Topic Modeling https://www.tidytextmining.com/topicmodeling.html

LS0tCnRpdGxlOiAiRW1waXJpY2FsIFdvcmsgLSBDbGltYXRlIENoYW5nZSBEaXNjb3Vyc2UgQ29ycG9yYSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyMgTG9hZGluZyBMaWJyYXJpZXMKCmBgYHtyfQojIGxvYWQgbGlicmFyaWVzCgpsaWJyYXJ5KHF1YW50ZWRhKQpsaWJyYXJ5KHJlYWR0ZXh0KQpsaWJyYXJ5KHdvcmRjbG91ZCkKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkod29yZGNsb3VkMikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkodG0pCmxpYnJhcnkoInRleHRjYXQiKQpsaWJyYXJ5KCJxdWFudGVkYS50ZXh0cGxvdHMiKQpsaWJyYXJ5KCJxdWFudGVkYS50ZXh0c3RhdHMiKQpsaWJyYXJ5KCJnc3ViZm4iKQpsaWJyYXJ5KCJzcGFjeXIiKQoKc3BhY3lfaW5pdGlhbGl6ZShtb2RlbCA9ICJkZV9jb3JlX25ld3Nfc20iKQpgYGAKCiMjIFN0YXJ0IGhlcmUgdG8gbG9hZCBleGlzdGluZyBjb3Jwb3JhOgoKYGBge3J9CiMgbG9hZCBjb3JwdXMgZmlsZXMgCmZ1bGxfY29ycHVzID0gcmVhZFJEUygiY29ycG9yYS9mdWxsX2NvcnB1cy5yZHMiKQpmdWxsX2NvcnB1c19zZW50cyA9IHJlYWRSRFMoImNvcnBvcmEvZnVsbF9jb3JwdXNfc2VudHMucmRzIikKCnByb19jb3JwdXMgPSByZWFkUkRTKCJjb3Jwb3JhL3Byb19jb3JwdXMucmRzIikKY29udHJhX2NvcnB1cyA9IHJlYWRSRFMoImNvcnBvcmEvY29udHJhX2NvcnB1cy5yZHMiKQoKcHJvMjAwMCA9IHJlYWRSRFMoImNvcnBvcmEvcHJvMjAwMC5yZHMiKQpwcm85MDAgPSByZWFkUkRTKCJjb3Jwb3JhL3BybzkwMC5yZHMiKQpjb250cmEyMDAwID0gcmVhZFJEUygiY29ycG9yYS9jb250cmEyMDAwLnJkcyIpCmNvbnRyYTkwMCA9IHJlYWRSRFMoImNvcnBvcmEvY29udHJhOTAwLnJkcyIpCgpmZmZfZGVfY29ycHVzID0gcmVhZFJEUygiY29ycG9yYS9mZmZfZGVfY29ycHVzLnJkcyIpCmlrZW1fY29ycHVzID0gcmVhZFJEUygiY29ycG9yYS9pa2VtX2NvcnB1cy5yZHMiKQprbGltYXJlcF9jb3JwdXMgPSByZWFkUkRTKCJjb3Jwb3JhL2tsaW1hcmVwX2NvcnB1cy5yZHMiKQprbGltYWZha3Rlbl9jb3JwdXMgPSByZWFkUkRTKCJjb3Jwb3JhL2tsaW1hZmFrdGVuX2NvcnB1cy5yZHMiKQp6ZXJvX2NvcnB1cyA9IHJlYWRSRFMoImNvcnBvcmEvemVyb19jb3JwdXMucmRzIikKa29tbWFfY29ycHVzID0gcmVhZFJEUygiY29ycG9yYS9rb21tYV9jb3JwdXMucmRzIikKZWlrZV9jb3JwdXMgPSByZWFkUkRTKCJjb3Jwb3JhL2Vpa2VfY29ycHVzLnJkcyIpCmZmaF9jb3JwdXMgPSByZWFkUkRTKCJjb3Jwb3JhL2ZmaF9jb3JwdXMucmRzIikKYGBgCgoKCiMgRXhwbG9yaW5nIHRoZSBjb3JwdXMKCiMjIENvcnB1cyBzdGF0aXN0aWNzCgpgYGB7cn0KIyB0byBnZXQgaW5kZXggbnVtYmVyIAojaWRfcHJvID0gMTpuZG9jKHBybzkwMCkKYGBgCgojIFBsb3R0aW5nIE51bWJlciBvZiBTZW50ZW5jZXMKCmBgYHtyfQpwcm8yMDAwX3N1bSA8LSBzdW1tYXJ5KHBybzIwMDAsIG5kb2MocHJvMjAwMCkpCmNvbnRyYTIwMDBfc3VtIDwtIHN1bW1hcnkoY29udHJhMjAwMCkKcHJvOTAwX3N1bSA8LSBzdW1tYXJ5KHBybzkwMCwgbmRvYyhwcm85MDApKQpjb250cmE5MDBfc3VtIDwtIHN1bW1hcnkoY29udHJhOTAwLCBuZG9jKGNvbnRyYTkwMCkpCgojdG8gZ2V0IGlkIGFzIHggYXhpcwojaWRfcHJvWzE6MTAwXQojY29udHJhOTAwX3N1bSRpZAoKZ2dwbG90KHBybzIwMDBfc3VtLCBhZXMoaWQsIFNlbnRlbmNlcywgZ3JvdXA9MSkpICsKICBnZW9tX2xpbmUoKSArIAogIGdlb21fcG9pbnQoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9MCwgdmp1c3Q9MSwgaGp1c3Q9MSkpICsgCiAgZ2d0aXRsZSgiU2VudGVuY2VzIFBybzIwMDAiKQoKZ2dwbG90KGNvbnRyYTIwMDBfc3VtLCBhZXMoaWQsIFNlbnRlbmNlcywgZ3JvdXA9MSkpICsKICBnZW9tX2xpbmUoKSArIAogIGdlb21fcG9pbnQoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9MCwgdmp1c3Q9MSwgaGp1c3Q9MSkpICsgCiAgZ2d0aXRsZSgiU2VudGVuY2VzIENvbnRyYTIwMDAiKQoKYGBgCgpgYGB7cn0KcHJvOTAwX3N1bSA8LSBzdW1tYXJ5KHBybzkwMCwgbj0xMDApCmNvbnRyYTkwMF9zdW0gPC0gc3VtbWFyeShjb250cmE5MDAsIG49MTAwKQoKCmdncGxvdChwcm85MDBfc3VtLCBhZXMocHJvOTAwX3N1bSRpZCwgVG9rZW5zLCBncm91cD0xKSkgKwogIGdlb21fbGluZSgpICsgCiAgZ2VvbV9wb2ludCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT0wLCB2anVzdD0xLCBoanVzdD0xKSkgKyAKICBnZ3RpdGxlKCJUb2tlbnMgUHJvOTAwIikKCmdncGxvdChjb250cmE5MDBfc3VtLCBhZXMoY29udHJhOTAwX3N1bSRpZCwgVG9rZW5zLCBncm91cD0xKSkgKwogIGdlb21fbGluZSgpICsgCiAgZ2VvbV9wb2ludCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT0wLCB2anVzdD0xLCBoanVzdD0xKSkgKyAKICBnZ3RpdGxlKCJUb2tlbnMgQ29udHJhOTAwIikKCmBgYAoKYGBge3J9CmdncGxvdChwcm85MDBfc3VtLCBhZXMocHJvOTAwX3N1bSRpZCwgVHlwZXMsIGdyb3VwPTEpKSArIAogIGdlb21fbGluZSgpICsgCiAgZ2VvbV9wb2ludCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT0wLCB2anVzdD0xLCBoanVzdD0xKSkgKyAKICBnZ3RpdGxlKCJUeXBlcyBQcm85MDAiKQoKZ2dwbG90KGNvbnRyYTkwMF9zdW0sIGFlcyhjb250cmE5MDBfc3VtJGlkLCBUeXBlcywgZ3JvdXA9MSkpICsKICBnZW9tX2xpbmUoKSArIAogIGdlb21fcG9pbnQoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9MCwgdmp1c3Q9MSwgaGp1c3Q9MSkpICsgCiAgZ2d0aXRsZSgiVHlwZXMgQ29udHJhOTAwIikKCgpgYGAKCmBgYHtyfQpnZ3Bsb3QocHJvOTAwX3N1bSwgYWVzKFRva2VucywgVHlwZXMsIGdyb3VwPTEsIGxhYmVsPSBpZCkpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBmb3JtdWxhID0ieSB+IHgiLCBzZSA9IEZBTFNFKSArCiAgZ2VvbV90ZXh0KGNoZWNrX292ZXJsYXAgPSBUKSArCiAgZ2d0aXRsZSgiVHlwZS1Ub2tlbi1SZWxhdGlvbiBQcm85MDAiKQoKZ2dwbG90KGNvbnRyYTkwMF9zdW0sIGFlcyhUb2tlbnMsIFR5cGVzLCBncm91cD0xLCBsYWJlbD0gaWQpKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgZm9ybXVsYSA9InkgfiB4Iiwgc2UgPSBGQUxTRSkgKwogIGdlb21fdGV4dChjaGVja19vdmVybGFwID0gVCkgKwogIGdndGl0bGUoIlR5cGUtVG9rZW4tUmVsYXRpb24gQ29udHJhOTAwIikKYGBgCjw8PDw8PDwgVXBkYXRlZCB1cHN0cmVhbQojIFdvcmQgRnJlcXVlbmNpZXMKCgojIyAxLiBTdGVwOiBDcmVhdGUgREZNLCBMb2FkIFN0b3BsaXN0cyAKYGBge3J9CiMgc3RvcGxpc3RzCmRlX3N0b3B3b3JkcyA8LSBzdG9wd29yZHM6OnN0b3B3b3JkcygiZGUiLCBzb3VyY2U9InNub3diYWxsIikKZW5fc3RvcHdvcmRzIDwtIHN0b3B3b3Jkczo6c3RvcHdvcmRzKCJlbiIsIHNvdXJjZT0ic25vd2JhbGwiICkKY3VzdG9tX3N0b3B3b3JkcyA8LSByZWFkLnRhYmxlKCJkZV9jb21wbGV0ZS50eHQiLCBoZWFkZXI9Riwgc2VwPSJcbiIpCgoKCiMgYWRkIG93biBzdG9wd29yZHMgCmZ1bGxfc3RvcHdvcmRzIDwtIGMoZGVfc3RvcHdvcmRzLCAiZGFzcyIsICI9IiwgInRoZSIsICJzZWl0IiwgImFiIiwgImJlaW0iLCAiXG4iLCAibWFsIiwgImMiLCAifCIsICJtIiwgImtvbW1lbnRhcmUiLCAibmV1ZXN0ZSIsICJnZXBvc3RldCIsIGN1c3RvbV9zdG9wd29yZHMsIGVuX3N0b3B3b3JkcykKZGVfc3RvcHdvcmRzMSA8LSBjKGRlX3N0b3B3b3JkcywgImRhc3MiLCAiPSIsICJ0aGUiLCAic2VpdCIsICJhYiIsICJiZWltIiwgIlxuIiwgIm1hbCIsICJjIiwgIlxcfCIsInwiLCAibSIsICJrb21tZW50YXJlIiwgIm5ldWVzdGUiLCAiZ2Vwb3N0ZXQiLCAiYWRtaW4iLCAiY29va2llcyIsICJpbmhhbHRlIiwgImluaGFsdCIsICJuZXdzbGV0dGVyIiwgInBvc3RlbiIsICJ6dWdyaWZmIiwgInBhc3N3b3J0IiwgImdlc2Now7x0enQiLCAic2VpdGUiLCAid2Vic2l0ZSIsICJ3ZWJzZWl0ZSIsICJhbmQiLCAiMCIsICIxIiwgIjIiLCAiMyIsIjQiLCI1IiwiNiIsIjciLCI4IiwiOSIsICJtZmciLCJ3IiwidCIsIndlciIpCgojIGNyZWF0ZSBkZm0KZGZtX3AyMDAwIDwtIGRmbShwcm8yMDAwLCByZW1vdmU9ZnVsbF9zdG9wd29yZHMsIHJlbW92ZV9wdW5jdD1UUlVFLCByZW1vdmVfbnVtYmVycz1UUlVFKQpkZm1fYzIwMDAgPC0gZGZtKGNvbnRyYTIwMDAsIHJlbW92ZT1mdWxsX3N0b3B3b3JkcywgcmVtb3ZlX3B1bmN0PVRSVUUsIHJlbW92ZV9udW1iZXJzPVRSVUUpCmBgYAoKIyMgQ29ycHVzIENsZWFuaW5nOiBMZW1tYXRpemF0aW9uIC0+IG5ldyBsZW1tYXRpemVkIGRmbQpgYGB7cn0KIyBwcm8gCnNwX3BybzIwMDAgPC0gc3BhY3lfcGFyc2UocHJvMjAwMCwgcG9zPUZBTFNFLCBlbnRpdHk9RkFMU0UsIGRlcGVuZGVuY3k9RkFMU0UpCnNwX3BybzIwMDAkdG9rZW4gPC0gc3BfcHJvMjAwMCRsZW1tYQoKc3BfZGZtX3AyMDAwIDwtIGFzLnRva2VucyhzcF9wcm8yMDAwKSU+JQogIGRmbShyZW1vdmU9ZnVsbF9zdG9wd29yZHMsIHJlbW92ZV9wdW5jdD1UUlVFLCByZW1vdmVfbnVtYmVycz1UUlVFLCB0b2xvd2VyPVRSVUUpCgojIGNvbnRyYQpzcF9jb250cmEyMDAwIDwtIHNwYWN5X3BhcnNlKGNvbnRyYTIwMDAsIHBvcz1GQUxTRSwgZW50aXR5PUZBTFNFLCBkZXBlbmRlbmN5PUZBTFNFKQpzcF9jb250cmEyMDAwJHRva2VuIDwtIHNwX2NvbnRyYTIwMDAkbGVtbWEKCnNwX2RmbV9jMjAwMCA8LSBhcy50b2tlbnMoc3BfY29udHJhMjAwMCklPiUKICBkZm0ocmVtb3ZlPWZ1bGxfc3RvcHdvcmRzLCByZW1vdmVfcHVuY3Q9VFJVRSwgcmVtb3ZlX251bWJlcnM9VFJVRSwgdG9sb3dlcj1UUlVFKQpgYGAKCmBgYHtyfQpkZm1fcDIwMDAKZGZtX2MyMDAwCmBgYAoKIyMgMi4gU3RlcDogQ2hlY2sgVG9wZmVhdHVyZXMgb2YgREZNIC0+IG1vc3QgZnJlcXVlbnRseSBvY2N1cmluZyB0ZXJtcwpgYGB7cn0KdG9wZmVhdHVyZXMoc3BfZGZtX3AyMDAwLCBuPTUwKQp0b3BmZWF0dXJlcyhzcF9kZm1fYzIwMDAsIG49NTApCmBgYAoKYGBge3J9CnRmX3AyMDAwIDwtIHRvcGZlYXR1cmVzKHNwX2RmbV9wMjAwMCwgbj01MCkKdGZfYzIwMDAgPC0gdG9wZmVhdHVyZXMoc3BfZGZtX2MyMDAwLCBuPTUwKQpgYGAKYGBge3J9CnRleHRzdGF0X2ZyZXF1ZW5jeShzcF9kZm1fcDIwMDAsIG49NTApCmBgYAoKIyMgUGxvdHRpbmcgd29yZCBmcmVxdWVuY2llcwoKYGBge3J9CmtsaW1hX3AyMDAwIDwtIGRmbV9zZWxlY3Qoc3BfZGZtX3AyMDAwLCBwYXR0ZXJuPSJrbGltYSoiKQprbGltYV9jMjAwMCA8LSBkZm1fc2VsZWN0KHNwX2RmbV9jMjAwMCwgcGF0dGVybj0ia2xpbWEqIikKCgpgYGAKCmBgYHtyfQpmcmVxX3AyMDAwIDwtIHRleHRzdGF0X2ZyZXF1ZW5jeShzcF9kZm1fcDIwMDAsIG49NTApCmZyZXFfYzIwMDAgPC0gdGV4dHN0YXRfZnJlcXVlbmN5KHNwX2RmbV9jMjAwMCwgbj01MCkKCnBsb3RfcDIwMDAgPC0gd2l0aChmcmVxX3AyMDAwLCByZW9yZGVyKGZlYXR1cmUsIC1mcmVxdWVuY3kpKQpwbG90X2MyMDAwIDwtIHdpdGgoZnJlcV9jMjAwMCwgcmVvcmRlcihmZWF0dXJlLCAtZnJlcXVlbmN5KSkKCiNjcmVhdGUgcGxvdCBmb3IgZWlrZSBrbGltYSB3b3JkcyBmcmVxdWVuY2llcwpwbG90MSA8LSBnZ3Bsb3QoZnJlcV9wMjAwMCwgYWVzKHg9ZmVhdHVyZSwgeT1mcmVxdWVuY3kpKSArIAogIGdlb21fcG9pbnQoKStnZ3RpdGxlKCJQMjAwMCBGcmVxdWVuY2llcyIpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTkwLGhqdXN0PTEpKQojZ2dzYXZlKHBsb3Q9cGxvdDEsIHdpZHRoID0gMTAsIGhlaWdodCA9IDUsIGRwaT0zMDAsIGZpbGVuYW1lPSJrbGltYV9laWtlX3Bsb3QuanBlZyIgKQpwbG90MQoKI2NyZWF0ZSBwbG90IGZvciBrbGltYXJlcG9ydGVyIGtsaW1hIHdvcmRzIGZyZXF1ZW5jaWVzCnBsb3QyIDwtIGdncGxvdChmcmVxX2MyMDAwLCBhZXMoeD1mZWF0dXJlLCB5PWZyZXF1ZW5jeSkpICsgCiAgZ2VvbV9wb2ludCgpKyBnZ3RpdGxlKCJDMjAwMCBGcmVxdWVuY2llcyIpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTkwLGhqdXN0PTEpKSAKICAKI2dnc2F2ZShwbG90PXBsb3QyLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSA1LCBkcGk9MzAwLCBmaWxlbmFtZT0ia2xpbWFfa2xpbWFyZXBfcGxvdC5qcGVnIiApCnBsb3QyCmBgYAojIyBTYW1lIFBsb3QgZm9yICJLbGltYSIgV29yZHMKYGBge3J9CmZyZXFfa2xpbWFfcDIwMDAgPC0gdGV4dHN0YXRfZnJlcXVlbmN5KGtsaW1hX3AyMDAwLCBuPTUwKQpmcmVxX2tsaW1hX2MyMDAwIDwtIHRleHRzdGF0X2ZyZXF1ZW5jeShrbGltYV9jMjAwMCwgbj01MCkKCmZyZXFfa2xpbWFfcDIwMDAkZmVhdHVyZSA8LSB3aXRoKGZyZXFfa2xpbWFfcDIwMDAsIHJlb3JkZXIoZmVhdHVyZSwgLWZyZXF1ZW5jeSkpCmZyZXFfa2xpbWFfYzIwMDAkZmVhdHVyZSA8LSB3aXRoKGZyZXFfa2xpbWFfYzIwMDAsIHJlb3JkZXIoZmVhdHVyZSwgLWZyZXF1ZW5jeSkpCgojY3JlYXRlIHBsb3QgZm9yIGVpa2Uga2xpbWEgd29yZHMgZnJlcXVlbmNpZXMKcGxvdDEgPC0gZ2dwbG90KGZyZXFfa2xpbWFfcDIwMDAsIGFlcyh4PWZlYXR1cmUsIHk9ZnJlcXVlbmN5KSkgKyAKICBnZW9tX3BvaW50KCkrZ2d0aXRsZSgiUDIwMDAgS2xpbWEgRnJlcXVlbmNpZXMiKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT05MCxoanVzdD0xKSkKI2dnc2F2ZShwbG90PXBsb3QxLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSA1LCBkcGk9MzAwLCBmaWxlbmFtZT0ia2xpbWFfZWlrZV9wbG90LmpwZWciICkKcGxvdDEKCiNjcmVhdGUgcGxvdCBmb3Iga2xpbWFyZXBvcnRlciBrbGltYSB3b3JkcyBmcmVxdWVuY2llcwpwbG90MiA8LSBnZ3Bsb3QoZnJlcV9rbGltYV9jMjAwMCwgYWVzKHg9ZmVhdHVyZSwgeT1mcmVxdWVuY3kpKSArIAogIGdlb21fcG9pbnQoKSsgZ2d0aXRsZSgiQzIwMDAgS2xpbWEgRnJlcXVlbmNpZXMiKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT05MCxoanVzdD0xKSkgCiAgCiNnZ3NhdmUocGxvdD1wbG90Miwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gNSwgZHBpPTMwMCwgZmlsZW5hbWU9ImtsaW1hX2tsaW1hcmVwX3Bsb3QuanBlZyIgKQpwbG90MgpgYGAKIyMgUGxvdCBURi1JREYgKG5vdCB3b3JraW5nIHlldCEhISkKYGBge3J9CiMgd2VpZ2h0ZWQgd29yZHMKcDIwMDBfd2VpZ2h0IDwtIGRmbV93ZWlnaHQoc3BfZGZtX3AyMDAwLCBzY2hlbWU9InByb3AiKQpjMjAwMF93ZWlnaHQgPC0gZGZtX3dlaWdodChzcF9kZm1fYzIwMDAsIHNjaGVtZT0icHJvcCIpCgpyZWxmcmVxX3AyMDAwIDwtIHRleHRzdGF0X2ZyZXF1ZW5jeShwMjAwMF93ZWlnaHQsIG49NTApCnJlbGZyZXFfYzIwMDAgPC0gdGV4dHN0YXRfZnJlcXVlbmN5KGMyMDAwX3dlaWdodCwgbj01MCkKCiN0ZmlkZgpwMjAwMF90ZmlkZiA8LSBkZm1fdGZpZGYoc3BfZGZtX3AyMDAwKQpjMjAwMF90ZmlkZiA8LSBkZm1fdGZpZGYoc3BfZGZtX2MyMDAwKQoKI3Bsb3QzIDwtIHdpdGgocmVsZnJlcV9wMjAwMCwgcmVvcmRlcihmZWF0dXJlLCAtZnJlcWVuY3kpKQpyZWxmcmVxX3AyMDAwJGZlYXR1cmUgPC0gd2l0aChyZWxmcmVxX3AyMDAwLCByZW9yZGVyKGZlYXR1cmUsIC1mcmVxdWVuY3kpKQpwbG90MyA8LSBnZ3Bsb3QocmVsZnJlcV9wMjAwMCwgYWVzKHg9ZmVhdHVyZSwgeT1mcmVxdWVuY3kpKSArIAogIGdlb21fcG9pbnQoKStnZ3RpdGxlKCJQMjAwMCBGcmVxdWVuY2llcyIpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTkwLGhqdXN0PTEpKQojZ2dzYXZlKHBsb3Q9cGxvdDEsIHdpZHRoID0gMTAsIGhlaWdodCA9IDUsIGRwaT0zMDAsIGZpbGVuYW1lPSJrbGltYV9laWtlX3Bsb3QuanBlZyIgKQpwbG90MwpgYGAKYGBge3J9CnNwX2NvbnRyYTIwMDAKYGBgCgoKYGBge3J9CnByb19mcmVxX3RmaWRmIDwtIHAyMDAwX3RmaWRmICU+JQogIHRleHRzdGF0X2ZyZXF1ZW5jeShuPTEwLCBmb3JjZT1UUlVFKQoKY29uX2ZyZXFfdGZpZGYgPC0gYzIwMDBfdGZpZGYgJT4lCiAgdGV4dHN0YXRfZnJlcXVlbmN5KG49MTAsIGZvcmNlPVRSVUUpCgp0cGxvdF90ZmlkZl9wMjAwMCA8LSBnZ3Bsb3QoZGF0YT1wcm9fZnJlcV90ZmlkZiwKICAgICAgICAgICAgICAgICAgICAgIGFlcyh4PWZhY3Rvcihucm93KHByb19mcmVxX3RmaWRmKToxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICB5PWZyZXF1ZW5jeSkpICsKICBnZW9tX3BvaW50KCkgKwogIGNvb3JkX2ZsaXAoKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShicmVha3M9ZmFjdG9yKG5yb3cocHJvX2ZyZXFfdGZpZGYpOjEpLAogICAgICAgICAgICAgICAgICAgbGFiZWxzPXByb19mcmVxX3RmaWRmJGZlYXR1cmUpICsKICBsYWJzKHg9TlVMTCwgeT0idGYtaWRmIikKCnRwbG90X3RmaWRmX3AyMDAwCgp0cGxvdF90ZmlkZl9jMjAwMCA8LSBnZ3Bsb3QoZGF0YT1jb25fZnJlcV90ZmlkZiwKICAgICAgICAgICAgICAgICAgICAgIGFlcyh4PWZhY3Rvcihucm93KGNvbl9mcmVxX3RmaWRmKToxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICB5PWZyZXF1ZW5jeSkpICsKICBnZW9tX3BvaW50KCkgKwogIGNvb3JkX2ZsaXAoKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShicmVha3M9ZmFjdG9yKG5yb3coY29uX2ZyZXFfdGZpZGYpOjEpLAogICAgICAgICAgICAgICAgICAgbGFiZWxzPWNvbl9mcmVxX3RmaWRmJGZlYXR1cmUpICsKICBsYWJzKHg9TlVMTCwgeT0idGYtaWRmIikKCnRwbG90X3RmaWRmX2MyMDAwCmBgYAoKYGBge3J9CnRvcGZlYXR1cmVzKHAyMDAwX3RmaWRmLCBuPTIwKQp0b3BmZWF0dXJlcyhjMjAwMF90ZmlkZiwgbj0yMCkKI3AyMDAwX3dlaWdodAoKI3RleHRzdGF0X2ZyZXF1ZW5jeShwMjAwMF90ZmlkZiwgbj0xMCkKYGBgCgojIyMgQ29tcGFyaXNvbiBvZiBHcm91cHMvT3JpZ2luCmBgYHtyfQpkZm1fd2VpZ2h0X29yaWdpbiA8LSBmdWxsX2NvcnB1cyAlPiUKICAjY29ycHVzX3N1YnNldChvcmlnaW4gPiAyMDAwKSAlPiUKICB0b2tlbnMocmVtb3ZlX3B1bmN0ID0gVFJVRSkgJT4lCiAgdG9rZW5zX3JlbW92ZShkZV9zdG9wd29yZHMxKSAlPiUKICBkZm0oKSAlPiUKICBkZm1fd2VpZ2h0KHNjaGVtZSA9ICJwcm9wIikKCiMgQ2FsY3VsYXRlIHJlbGF0aXZlIGZyZXF1ZW5jeSBieSBwcmVzaWRlbnQKZnJlcV93ZWlnaHQgPC0gdGV4dHN0YXRfZnJlcXVlbmN5KGRmbV93ZWlnaHRfb3JpZ2luLCBuID0gMTAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBzID0gZGZtX3dlaWdodF9vcmlnaW4kZ3JvdXApICMgY2hhbmdlIHRvICJvcmlnaW4iIGhlcmUgdG8gc2VlIGZvciBhbGwgd2Vic2l0ZXMgCgpnZ3Bsb3QoZGF0YSA9IGZyZXFfd2VpZ2h0LCBhZXMoeCA9IG5yb3coZnJlcV93ZWlnaHQpOjEsIHkgPSBmcmVxdWVuY3kpKSArCiAgICAgZ2VvbV9wb2ludCgpICsKICAgICBmYWNldF93cmFwKH4gZ3JvdXAsIHNjYWxlcyA9ICJmcmVlIikgKwogICAgIGNvb3JkX2ZsaXAoKSArCiAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IG5yb3coZnJlcV93ZWlnaHQpOjEsCiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGZyZXFfd2VpZ2h0JGZlYXR1cmUpICsKICAgICBsYWJzKHggPSBOVUxMLCB5ID0gIlJlbGF0aXZlIGZyZXF1ZW5jeSIpCmBgYAojIENvbGxvY2F0aW9ucwpgYGB7cn0KIyB0byByZW1vdmUgc3BlY2lhbCBjaGFycyBmcm9tIGNvcnB1cwpwcm8yMDAwIDwtIGdzdWIoIlxcfCIsICIiLCBwcm8yMDAwKQpwcm8yMDAwIDwtIGdzdWIoIj0iLCAiIiwgcHJvMjAwMCkKCiMgY29udmVydCBpbnRvIGNvbGxvY2F0aW9uIGRhdGFmcmFtZQpwX2NvbGwgPC0gdGV4dHN0YXRfY29sbG9jYXRpb25zKHBybzIwMDAsIG1pbl9jb3VudD01MCkKYXJyYW5nZShwX2NvbGwsIGRlc2MoY291bnQpKQpgYGAKYGBge3J9CiMgdHJhbnNmb3JtIHN0b3BsaXN0cyBmb3IgZHBseXI6OmZpbHRlciBmdW5jdGlvbiAod2h5PykKZGVfc3RwcyA8LSBwYXN0ZTAoZGVfc3RvcHdvcmRzLCBjb2xsYXBzZSA9ICJcXGJ8XFxiIikKZW5fc3RwcyA8LSBwYXN0ZTAoZW5fc3RvcHdvcmRzLCBjb2xsYXBzZSA9ICJcXGJ8XFxiIikKCiMgcmVtb3ZlIGVudHJpZXMgaW52b2x2aW5nIHN0b3B3b3JkczogTk9UIFdPUktJTkcgWUVUIQpwMjAwMF9jb2xsX2NsZWFuIDwtIHBfY29sbCAlPiUKICBkcGx5cjo6ZmlsdGVyKCFzdHJfZGV0ZWN0KGNvbGxvY2F0aW9uLCBkZV9zdHBzKSwKICAgICAgICAgICAgICAgICFzdHJfZGV0ZWN0KGNvbGxvY2F0aW9uLCBlbl9zdHBzKSwKICAgICAgICAgICAgICAgICFzdHJfZGV0ZWN0KGNvbGxvY2F0aW9uLCAiPSIpKQoKI3AyMDAwX2NvbGxfY2xlYW4KYXJyYW5nZShwMjAwMF9jb2xsX2NsZWFuLCBkZXNjKGNvdW50KSkKYGBgCgpgYGB7cn0KIyBjb2xsb2NhdGlvbnMgbWl0IHZvcmhlcmlnZW0gc3RvcHdvcmRzIHJlbW92YWw6IG5vdCB3b3JraW5nCnAyMDAwX3Rva3MgPC0gdG9rZW5zKHBybzIwMDApCnAyMDAwX3Rva3Nfc3cgPC0gdG9rZW5zX3NlbGVjdChwMjAwMF90b2tzLCBwYXR0ZXJuPWZ1bGxfc3RvcHdvcmRzLCBzZWxlY3Rpb249InJlbW92ZSIpCgpwMjAwMF9jb2xsIDwtIHRleHRzdGF0X2NvbGxvY2F0aW9ucyhwMjAwMF90b2tzX3N3LCBtaW5fY291bnQ9MykKYXJyYW5nZShwMjAwMF9jb2xsLCBkZXNjKGNvdW50KSkKYGBgCmBgYHtyfQpzdW1tYXJ5KGZ1bGxfY29ycHVzLCBuPTUpCmBgYAoKIyMgQ29tcGFyaXNvbiBQbG90cwpgYGB7cn0KI2NyZWF0ZSBpbnB1dApjb3JwIDwtIGRmbShmdWxsX2NvcnB1cykKCiMgbGVtbWF0aXNpZXJ1bmcgdmVyc3VjaGVuOgoKCgpkZV9rbGltYSA8LSBkZm1fc2VsZWN0KGNvcnAsIHBhdHRlcm4gPSJrbGltYSoiKQpkZV9yZWxmcmVxIDwtIGRmbV93ZWlnaHQoZGVfa2xpbWEsIHNjaGVtZT0icHJvcCIpCmRlX2ZyZXFzIDwtIHRleHRzdGF0X2ZyZXF1ZW5jeShkZV9yZWxmcmVxLCBncm91cHM9Z3JvdXApCgojcGxvdHRpbmcgCmZyZXFzLmFjdCA8LSBmaWx0ZXIoZGVfZnJlcXMsIGdyb3VwID09ICJhY3RpdmlzdHMiKSAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSBzZWxlY3QoZmVhdHVyZSwgZnJlcXVlbmN5KQpmcmVxcy5zY2VwdCA8LSBmaWx0ZXIoZGVfZnJlcXMsIGdyb3VwID09ICJzY2VwdGljcyIpICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIHNlbGVjdChmZWF0dXJlLCBmcmVxdWVuY3kpCmZyZXFzIDwtIGxlZnRfam9pbihmcmVxcy5hY3QsIGZyZXFzLnNjZXB0LCBieSA9ICJmZWF0dXJlIikgJT4lIGhlYWQoMzApICU+JSBhcnJhbmdlKGZyZXF1ZW5jeS54KSAlPiUgbXV0YXRlKGZlYXR1cmUgPSBmYWN0b3IoZmVhdHVyZSwgZmVhdHVyZSkpCmdncGxvdChmcmVxcykgKwogIGdlb21fc2VnbWVudChhZXMoeD1mZWF0dXJlLCB4ZW5kPWZlYXR1cmUsIHk9ZnJlcXVlbmN5LngsIHllbmQ9ZnJlcXVlbmN5LnkpLCBjb2xvcj0iZ3JleSIpICsKICBnZW9tX3BvaW50KGFlcyh4PWZlYXR1cmUsIHk9ZnJlcXVlbmN5LngpLCBjb2xvciA9ICJyZWQiLCBzaXplID0gMyApICsKICBnZW9tX3BvaW50KGFlcyh4PWZlYXR1cmUsIHk9ZnJlcXVlbmN5LnkpLCBjb2xvciA9ICJsaWdodGJsdWUiLCBzaXplID0gMyApICsKICBnZ3RpdGxlKCJXb3JkIEZyZXF1ZW5jaWVzIikgKyAKICB4bGFiKCIiKSArIHlsYWIoIldvcnRmcmVxdWVueiIpICsgCiAgY29vcmRfZmxpcCgpCgpmcmVxcy5hY3QgCmZyZXFzLnNjZXB0CmBgYApgYGB7cn0KCmRlX2tsaW1hX3BybyA8LSBkZm1fc2VsZWN0KHNwX3BybzIwMDBfZGZtLCBwYXR0ZXJuID0ia2xpbWEqIikKZGVfcmVsZnJlcV9wcm8gPC0gZGZtX3dlaWdodChkZV9rbGltYV9wcm8sIHNjaGVtZT0icHJvcCIpCmRlX2ZyZXFzX3BybyA8LSB0ZXh0c3RhdF9mcmVxdWVuY3koZGVfcmVsZnJlcV9wcm8pCgpkZV9rbGltYV9jb24gPC0gZGZtX3NlbGVjdChzcF9jb24yMDAwX2RmbSwgcGF0dGVybiA9ImtsaW1hKiIpCmRlX3JlbGZyZXFfY29uIDwtIGRmbV93ZWlnaHQoZGVfa2xpbWFfY29uLCBzY2hlbWU9InByb3AiKQpkZV9mcmVxc19jb24gPC0gdGV4dHN0YXRfZnJlcXVlbmN5KGRlX3JlbGZyZXFfY29uKQoKCiNwbG90dGluZyAKZnJlcXMuYWN0IDwtIGZpbHRlcihkZV9mcmVxc19wcm8pICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIHNlbGVjdChmZWF0dXJlLCBmcmVxdWVuY3kpCmZyZXFzLnNjZXB0IDwtIGZpbHRlcihkZV9mcmVxc19jb24pICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIHNlbGVjdChmZWF0dXJlLCBmcmVxdWVuY3kpCmZyZXFzIDwtIGxlZnRfam9pbihmcmVxcy5hY3QsIGZyZXFzLnNjZXB0LCBieSA9ICJmZWF0dXJlIikgJT4lIGhlYWQoMzApICU+JSBhcnJhbmdlKGZyZXF1ZW5jeS54KSAlPiUgbXV0YXRlKGZlYXR1cmUgPSBmYWN0b3IoZmVhdHVyZSwgZmVhdHVyZSkpCnAgPC0gZ2dwbG90KGZyZXFzKSArCiAgICBnZW9tX3NlZ21lbnQoYWVzKHg9ZmVhdHVyZSwgeGVuZD1mZWF0dXJlLCB5PWZyZXF1ZW5jeS54LCB5ZW5kPWZyZXF1ZW5jeS55KSwgY29sb3I9ImdyZXkiKSArCiAgICBnZW9tX3BvaW50KGFlcyh4PWZlYXR1cmUsIHk9ZnJlcXVlbmN5LngsIGNvbG91cj0iQWN0aXZpc3RzIiksIHNpemUgPSAzKSArCiAgICBnZW9tX3BvaW50KGFlcyh4PWZlYXR1cmUsIHk9ZnJlcXVlbmN5LnksIGNvbG91cj0iU2NlcHRpY3MiKSwgc2l6ZSA9IDMgKSArCiAgICBnZ3RpdGxlKCJXb3JkIEZyZXF1ZW5jaWVzIikgKyAKICAgIHhsYWIoIiIpICsgeWxhYigiRnJlcXVlbmN5IikgKwogICAgY29vcmRfZmxpcCgpCgpwK2xhYnMoY29sb3VyPSJHcm91cCIpCgpgYGAKCgpgYGB7cn0KIyB0byBnZXQgbGVtbWF0aXplZCBkZm0gCnNwX3BybzIwMDBfZGZtIDwtIGFzLnRva2VucyhzcF9wcm8yMDAwKSAlPiUKICBkZm0oKQoKc3BfY29uMjAwMF9kZm0gPC0gYXMudG9rZW5zKHNwX2NvbnRyYTIwMDApICU+JQogIGRmbSgpCgpgYGAKCgoKYGBge3J9CmRmbV93ZWlnaHRfY29ycCA8LSBmdWxsX2NvcnB1cyAlPiUKICB0b2tlbnMocmVtb3ZlX3B1bmN0ID0gVFJVRSkgJT4lCiAgdG9rZW5zX3JlbW92ZShkZV9zdG9wd29yZHMxKSAlPiUKICBkZm0oKSAlPiUKICBkZm1fd2VpZ2h0KHNjaGVtZSA9ICJwcm9wIikKCiMgQ2FsY3VsYXRlIHJlbGF0aXZlIGZyZXF1ZW5jeSBieSBwcmVzaWRlbnQKZnJlcV93ZWlnaHQgPC0gdGV4dHN0YXRfZnJlcXVlbmN5KGRmbV93ZWlnaHRfY29ycCwgbiA9IDEwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwcyA9IGRmbV93ZWlnaHRfY29ycCRvcmlnaW4pCgpnZ3Bsb3QoZGF0YSA9IGZyZXFfd2VpZ2h0LCBhZXMoeCA9IG5yb3coZnJlcV93ZWlnaHQpOjEsIHkgPSBmcmVxdWVuY3kpKSArCiAgICAgZ2VvbV9wb2ludCgpICsKICAgICBmYWNldF93cmFwKH4gZ3JvdXAsIHNjYWxlcyA9ICJmcmVlIikgKwogICAgIGNvb3JkX2ZsaXAoKSArCiAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IG5yb3coZnJlcV93ZWlnaHQpOjEsCiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGZyZXFfd2VpZ2h0JGZlYXR1cmUpICsKICAgICBsYWJzKHggPSBOVUxMLCB5ID0gIlJlbGF0aXZlIGZyZXF1ZW5jeSIpCmBgYApgYGB7cn0Kc3VtbWFyeShmdWxsX2NvcnB1cywgbj0xMCkKYGBgCgojIyBLZXluZXNzCmBgYHtyfQojIENyZWF0ZSBhIGRmbSBncm91cGVkIGJ5IHByZXNpZGVudApjb3JwX2RmbSA8LSB0b2tlbnMoZnVsbF9jb3JwdXMsIHJlbW92ZV9wdW5jdCA9IFRSVUUpICU+JQogIHRva2Vuc19yZW1vdmUoZGVfc3RvcHdvcmRzMSkgJT4lCiAgdG9rZW5zX2dyb3VwKGdyb3VwcyA9IGdyb3VwKSAlPiUKICBkZm0oKQoKIyBDYWxjdWxhdGUga2V5bmVzcyBhbmQgZGV0ZXJtaW5lIFRydW1wIGFzIHRhcmdldCBncm91cApyZXN1bHRfa2V5bmVzcyA8LSB0ZXh0c3RhdF9rZXluZXNzKGNvcnBfZGZtLCB0YXJnZXQgPSAiYWN0aXZpc3RzIikKCiMgUGxvdCBlc3RpbWF0ZWQgd29yZCBrZXluZXNzCnRleHRwbG90X2tleW5lc3MocmVzdWx0X2tleW5lc3MsIG1hcmdpbj0wLjIsIG49MTApIApgYGAKIyMgQ29tcGFyaXNvbiBDbG91ZApgYGB7cn0KZnVsbF9jb3JwdXMgJT4lCiAgICB0b2tlbnMocmVtb3ZlX3B1bmN0ID0gVFJVRSwgcmVtb3ZlX251bWJlcnM9VFJVRSkgJT4lCiAgICB0b2tlbnNfcmVtb3ZlKGRlX3N0b3B3b3JkczEpICU+JQogICAgZGZtKCkgJT4lCiAgICBkZm1fZ3JvdXAoZ3JvdXBzID0gZ3JvdXApICU+JQogICAgZGZtX3RyaW0obWluX3Rlcm1mcmVxID0gNSwgdmVyYm9zZSA9IEZBTFNFKSAlPiUKICAgIHRleHRwbG90X3dvcmRjbG91ZChjb21wYXJpc29uID0gVFJVRSwgbWF4X3dvcmRzPTEwMCkKICAgICAgICAgICAgICAgICAgICAgICAjLGNvbG9yPWMoImxpZ2h0Ymx1ZSIsImJsdWUiKSkKYGBgCmBgYHtyfQp0ZXh0cGxvdF94cmF5KAogICAga3dpYyh0b2tlbnMocHJvMjAwMCksIHBhdHRlcm4gPSAia2xpbWEqIiksCiAgICBrd2ljKHRva2Vucyhjb250cmEyMDAwKSwgcGF0dGVybiA9ICJrbGltYSoiKSkKYGBgCiMgVG9waWMgTW9kZWxpbmcKYGBge3J9CmxpYnJhcnkodGlkeXRleHQpCmxpYnJhcnkodG9waWNtb2RlbHMpCmBgYAoKYGBge3J9CmRmbV9mdWxsIDwtIGRmbShmdWxsX2NvcnB1cywgcmVtb3ZlPWRlX3N0b3B3b3JkczEsIHJlbW92ZV9wdW5jdD1UUlVFLCByZW1vdmVfbnVtYmVycz1UUlVFKQpkZm1fZnVsbAoKdG1fZnVsbDwtY29udmVydChkZm1fZnVsbCwgdG89InRvcGljbW9kZWxzIikKCnRvcGljTW9kZWwgPC0gTERBKHRtX2Z1bGwsIGs9NSwgbWV0aG9kPSJHaWJicyIsIGNvbnRyb2w9bGlzdChpdGVyID0gNTAwLCB2ZXJib3NlID0gMjUpKQp0ZXJtcyh0b3BpY01vZGVsLCAxMCkKYGBgCgoKYGBge3J9CmFwX2xkYSA8LSBMREEodG1fZnVsbCwgaz01LCBjb250cm9sPWxpc3Qoc2VlZD0xMjM0KSkKCmFwX3RvcGljcyA8LSB0aWR5KGFwX2xkYSwgbWF0cml4PSJiZXRhIikKCmFwX2xkYQoKCmFwX3RvcF90ZXJtcyA8LSBhcF90b3BpY3MgJT4lCiAgZ3JvdXBfYnkodG9waWMpICU+JQogIHNsaWNlX21heChiZXRhLCBuID0gMTApICU+JSAKICB1bmdyb3VwKCkgJT4lCiAgYXJyYW5nZSh0b3BpYywgLWJldGEpCgphcF90b3BfdGVybXMgJT4lCiAgbXV0YXRlKHRlcm0gPSByZW9yZGVyX3dpdGhpbih0ZXJtLCBiZXRhLCB0b3BpYykpICU+JQogIGdncGxvdChhZXMoYmV0YSwgdGVybSwgZmlsbCA9IGZhY3Rvcih0b3BpYykpKSArCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGZhY2V0X3dyYXAofiB0b3BpYywgc2NhbGVzID0gImZyZWUiKSArCiAgc2NhbGVfeV9yZW9yZGVyZWQoKQoKYGBgCi0gdHJ5IGxlbW1hdGl6ZWQgdmVyc2lvbiBmb3IgdG9waWMgbW9kZWxpbmcgCgoKSWRlYXM6CkRPTkU6IFdvcmRjbG91ZCBQbG90IG9mIENvbXBhcmlzb24gR3JvdXA6CiAgICAgIGh0dHBzOi8vcXVhbnRlZGEuaW8vYXJ0aWNsZXMvcGtnZG93bi9leGFtcGxlcy9wbG90dGluZy5odG1sCgpMZXhpY2FsIERpc3BlcnNpb24gUGxvdCAoWC1SYXkpCi0+IGNvdWxkIGJlIGRvbmUgZm9yIGtleXdvcmRzICJrbGltYSoiCgpOZXh0OgotIENhbGN1bGF0ZSAiQ29ycHVzIFNpbWlsYXJpdHkiCi0gS2xpbWF3w7ZydGVyIExpc3RlIG1pdCBHcm91cCB1bmQgQ291bnRzIGFic3BlaWNoZXJuIC0+IHdlbGNoZSBLbGltYXfDtnJ0ZXIgZ2lidCBlcyB3byB1bmQgd2llIG9mdAotIGFsbGVzIG1pdCBkZXIgIlNlbnRzIiBWZXJzaW9uIHRlc3RlbgotIEFuYWx5c2UgZGVyIEVyZ2Vibmlzc2UKLSBMaXRlcmF0dXItUmVjaGVyY2hlIHp1IGRlbiBUZXh0bWluaW5nIFRoZW1lbgoKVG9waWMgTW9kZWxpbmcKaHR0cHM6Ly93d3cudGlkeXRleHRtaW5pbmcuY29tL3RvcGljbW9kZWxpbmcuaHRtbAoKCgoKCg==